import { Injectable, Inject, OnInit } from "@angular/core";
import {
  Observable,
  Subject,
  ReplaySubject,
  from,
  of,
  range,
  BehaviorSubject
} from "rxjs";
import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
import { Router, NavigationEnd } from "@angular/router";
import { ActivatedRoute } from "@angular/router";

import * as _ from "lodash";

// declare var localStorage;

const computed = fn => {
  return fn();
};

const localStore = {
  name: "ehStore",
  set(v) {
    // localStorage.ehStore = v;
  },
  get() {
    // const store = JSON.parse(localStorage[this.name]);
    // if (!this.has()) {
    //   return {};
    // }
    // return store;
  },
  del() {
    // localStorage.removeItem(this.name);
  },
  has() {
    // const store = JSON.parse(localStorage[this.name] || "{}");
    // if (store === "undefined") {
    //   return false;
    // }
    // if (JSON.stringify(store) === "{}") {
    //   return false;
    // }
    // if (!store) {
    //   return false;
    // }
    // return true;
  },
  isEmpty() {
    return !(this.has() && JSON.stringify(this.get()) !== "{}");
  }
};

@Injectable({
  providedIn: "root"
})
export class StoreService {
  state: any = {
    query: {},
    user: {
      login: {
        username: String,
        password: String,
        remember: Boolean,
        verify: String
      },
      info: {
        email: "",
        phone: "",
        nickname: "",
        name: "",
        gender: "",
        birthday: "",
        address: "",
        job: "",
        edu: "",
        salary: "",
        sign: ""
      }
    },
    good: {
      save: {}
    },
    common: {
      config: {}
    }
  };

  sub: any;

  constructor(
    @Inject("UserService") private userService,
    @Inject("EmailCodeService") private emailCodeService,
    @Inject("PhoneCodeService") private phoneCodeService,
    @Inject("ConfigService") private configService,
    @Inject("GoodService") private goodService,
    private activatedRoute: ActivatedRoute,
    private router: Router
  ) {
    this.init();
  }

  init() {
    this.sub = new ReplaySubject();
    // if (!localStore.isEmpty()) {
    //   // logout 要清楚本地持久数据
    //   this.commit(localStore.get());
    // }
    this.addListen();
  }

  commit(state) {
    _.merge(this.state, state);
    localStore.set(JSON.stringify(this.state));
    this.sub.next(this.state);
  }

  async dispatch(type, params) {
    return await this[type](this.state, params);
  }

  async test() {
    const res = await this.userService.select().toPromise();
  }

  subscribe(callback) {
    return this.sub.subscribe(callback);
  }

  addListen() {
    this.subscribe(state => {});
    this.router.events.subscribe(
      (val: any) => {
        if (val instanceof NavigationEnd) {
          if (val.url === "/u/login") {
          }
        }
      },
      () => {},
      () => {}
    );

    this.activatedRoute.queryParams.subscribe(async params => {
      await this.commit(
        _.merge(this.state, {
          query: {
            ...params
          }
        })
      );
    });
  }

  afterFn(fn, afterFn) {
    return function() {
      const ret = fn.apply(this, arguments);
      afterFn.apply(this, arguments);
      return ret;
    };
  }
  async logout(state, params) {
    localStore.del();
  }
  // action
  async doLogin(state, params) {
    const res = await this.userService
      .find({
        username: params.username,
        type: params.type,
        password: params.password,
        verify: params.verify
      })
      .toPromise();
    await this.commit(
      _.merge(state, {
        user: {
          login: {
            ...params
          },
          info: res.data
        }
      })
    );
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async doEnroll(state, params) {
    const res = await this.userService
      .add({
        ...params
      })
      .toPromise();
    await this.commit(
      _.merge(state, {
        user: {
          login: { ...params }
        }
      })
    );
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async findUser(state, params) {
    console.log(88888888, params);
    const res = await this.userService.find(params).toPromise();
    await this.commit(
      _.merge(state, {
        user: {
          info: res.data
        }
      })
    );
    return res;
  }

  async sendEmailCode(state, { email }) {
    const res = await this.emailCodeService
      .add({ email, type: this.state.common.config.isEmail })
      .toPromise();
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async sendPhoneCode(state, { phone }) {
    const res = await this.phoneCodeService
      .add({ phone, type: this.state.common.config.isPhone })
      .toPromise();
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async saveUser(state, params) {
    const res = await this.userService
      .save(params.id || state.user.info._id, { ...params })
      .toPromise();
    if ("200" === res.code) {
      await this.commit(
        _.merge(state, {
          user: {
            info: res.data
          }
        })
      );
    }
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async addGood(state, params) {
    const res = await this.goodService.add({ ...params }).toPromise();
    if ("200" === res.code) {
      await this.commit(
        _.merge(state, {
          good: {
            save: res.data
          }
        })
      );
    }
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async saveGood(state, params) {
    const p = {
      ...params
    };
    delete p.id;
    const res = await this.goodService.save(params.id, { ...p }).toPromise();
    if ("200" === res.code) {
      await this.commit(
        _.merge(state, {
          good: {
            save: res.data
          }
        })
      );
    }
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async findGood(state, params) {
    const res = await this.goodService.find(params.id).toPromise();
    if ("200" === res.code) {
      await this.commit(
        _.merge(state, {
          good: {
            save: res.data
          }
        })
      );
    }
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async delGoodImgs(state, params) {
    const data = {
      ...params
    };
    delete data.id;
    const res = await this.goodService.del(params.id, data).toPromise();
    if ("200" === res.code) {
      // await this.commit(
      //   _.merge(state, {
      //     good: {
      //       save: res.data,
      //     },
      //   }),
      // );
    }
    return new Promise(resolve => {
      resolve(res);
    });
  }

  async selectConfig(state) {
    const res = await this.configService.select().toPromise();
    await this.commit(
      _.merge(state, {
        common: {
          config: res.data
        }
      })
    );
    return new Promise(resolve => {
      resolve(res);
    });
  }
}
